﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Yto.Common.Dependency;
using Yto.EF.DbCtx;
using Yto.Unitwork;

namespace Yto.EF.UW
{
    public class EFTransaction : IEFTransaction , ITransient
    {
        protected UnitworkOptions UnitworkOption { get; private set; }

        protected TransactionScope transactionScope;

        protected List<DbContext> listDbContext;

        public EFTransaction()
        {
            listDbContext = new List<DbContext>();
        }

        public void Commit()
        {
            if(transactionScope == null)
            {
                return;
            }
            transactionScope.Complete();

            transactionScope.Dispose();
            transactionScope = null;
        }

        public void Init(UnitworkOptions option)
        {
            UnitworkOption = option;

            InitTransaction();
        }

        private void InitTransaction()
        {
            if(transactionScope !=null)
            {
                return;
            }

            var trsctOption = new TransactionOptions()
            {
                IsolationLevel = UnitworkOption.IsltLvl.GetValueOrDefault(IsolationLevel.ReadCommitted)
            };

            //timeout

            transactionScope = new TransactionScope(
                UnitworkOption.TrsctScpOpt.GetValueOrDefault(TransactionScopeOption.Required),
                trsctOption,
                UnitworkOption.AsyncFlowOpt.GetValueOrDefault(TransactionScopeAsyncFlowOption.Enabled)
                );
        }

        public void Dispose(ICtnResolver ctnResolver)
        {
            foreach(var ctx in listDbContext)
            {
                ctnResolver.Realse(ctx);
            }
            listDbContext.Clear();

            if(transactionScope != null)
            {
                transactionScope.Dispose();
                transactionScope = null;
            }
        }

        public DbContext GetDbContext<T>(string connStr, IDbResolver dbResolver) where T : DbContext
        {
            var ctx = dbResolver.Resolver<T>(connStr);
            listDbContext.Add(ctx);
            return ctx;
        }
    }
}
